﻿package  {
	import flash.utils.Timer;
	import flash.events.TimerEvent;
	import flash.utils.getTimer;
	
	public class GameLoop {

		public static const FRAME_RATE:int = 60;
		private var _period:Number = 1000 / FRAME_RATE; // lama satu frame dalam milisekon
		private var _beforeTime:int = 0; // waktu sebelum siklus
		private var _afterTime:int = 0; // waktu setelah siklus 
		private var _timeDiff:int = 0; // waktu yang dibutuhkan untuk melakukan satu siklus
		private var _sleepTime:int = 0;	// waktu tidur(bisa negatif)			
		private var lastUpdateTime : Number; // waktu terakhir update
		private var lastRenderTime : Number; // waktu terakhir render
		
		private var gameTimer : Timer;
		private var game : BaseGame;			

		public function GameLoop(game:BaseGame) {
			gameTimer = new Timer(_period);
			this.game = game;
			gameTimer.addEventListener(TimerEvent.TIMER, runGame);			
		}
		
		private function runGame(e:TimerEvent):void {	
			_beforeTime = getTimer();
			
			game.update((_beforeTime - lastUpdateTime) / 1000.0);
			game.render((_beforeTime - lastRenderTime) / 1000.0);
			e.updateAfterEvent();							   
			
			_afterTime = getTimer();
			lastUpdateTime = _afterTime;
			lastRenderTime = _afterTime;
			_timeDiff = _afterTime - _beforeTime;
			_sleepTime = (_period - _timeDiff); 
			
			gameTimer.reset();
			if(_sleepTime > 0) {
				//kalo ternyata satu siklus makan waktu lebih kecil dari frame period
				gameTimer.delay = _sleepTime;
			}						
			
			while(_sleepTime < 0) {
				//kalo ternyata satu siklus makan waktu lebih besar dari frame period
				var curTime = getTimer();
				game.update((curTime - lastUpdateTime) / 1000.0);
				lastUpdateTime = getTimer();
				_sleepTime += _period;							
			}
			
			gameTimer.start();			
		}
		
		public function start():void {
			gameTimer.start();						
			lastUpdateTime = getTimer();
			lastRenderTime = getTimer();
		}
		
		public function stop():void {
			gameTimer.stop();
			gameTimer.removeEventListener(TimerEvent.TIMER, runGame);			
		}
	}
	
}
